/*
 * TermSequentialFile.h
 *
 *  Created on: Nov 26, 2012
 *      Author: m
 */

#ifndef TERMSEQUENTIALFILE_H_
#define TERMSEQUENTIALFILE_H_

#include "../common_components/FixedSizeBlockSequentialFile.h"
#include "../serializers/TermSerializer.h"
#include "Term.h"

#define TERM_SIZE_IN_BYTES 40

namespace physical
{

/**
 * Archivo secuencial de Términos
 *
 * Los términos tienen una limitación de
 *  tamaño total de 40 bytes
 */
class TermSequentialFile
{
public:

    /**
     * Constructor por defecto
     */
    TermSequentialFile();

    /**
     * Constructor por valor
     *
     * Crea un TermSequentialFile
     *  y le asocia un archvo, abierto en
     *  el modo indicado. Si no se indica
     *  ningún modo se abre en el modo
     *  por defecto ( in | out | app )
     *
     * @param filename Nombre del archivo a asociar
     * @param mode Modo de apertura. Valor por
     *              defecto: ( in | out | app )
     */
    TermSequentialFile( const char* filename,
            openmode mode = s_defaultOpenmode );

    /**
     * Destructor
     */
    virtual ~TermSequentialFile();

    /**
     * Devuelve el Term siguiente
     *
     * @return el término siguiente
     */
    Term get();

    /**
     * Guarda un nuevo Term al final del archivo
     *
     * @param term Término a guardar
     * @return posición en la que se guardó el termino
     *          La posición del primer término es 1.
     */
    size_t put( const Term& term );

    /**
     * Verifica si existen más términos para leer
     *
     * @return true si existen más terminos para
     *          leer, false en caso contrario
     */
    bool hasNext();

    /**
     * Asocia un archivo al TermSequentialFile
     *
     * @param filename Nombre del archivo
     * @param mode Modo de apertura
     */
    void open( const char* filename, openmode mode = s_defaultOpenmode );

    /**
     * Desasocia un archivo del TermSequentialFile
     */
    void close();

protected:
    static const openmode s_defaultOpenmode = std::ios_base::in | std::ios_base::out | std::ios_base::app;

    std::unique_ptr< FixedSizeBlockSequentialFile< TERM_SIZE_IN_BYTES > > m_file;
    std::unique_ptr< Serializer< Term > > m_serializer;
};

/*
 * Excepciónes
 */

/**
 * Excepción Genérica de TermSequentialFile
 */
class TermSequentialFileException : public PhysicalException
{
};

/**
 * Excepción: El Término es demasiado largo
 */
class TermIsTooLongException : public TermSequentialFileException
{
    virtual const char* what() const throw()
    {
        return "Term is too long.";
    }
};

} /* namespace physical */
#endif /* TERMSEQUENTIALFILE_H_ */
